package com.cictec.middleware.gps.engine.position.handler;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.cictec.middleware.commons.utils.Constants;
import com.cictec.middleware.commons.utils.PMSUtils;
import com.cictec.middleware.commons.utils.PropertiesUtils;
import com.cictec.middleware.commons.utils.gps.CoordinateConversion;
import com.cictec.middleware.commons.utils.gps.CoordinateConversion.UTMPoint;
import com.cictec.middleware.core.entity.BusLineStation;
import com.cictec.middleware.gps.engine.BusInstance;
import com.cictec.middleware.gps.engine.TimingPoint;
import com.cictec.middleware.gps.engine.exception.BusPositionHandlerException;
import com.cictec.middleware.gps.engine.position.BusPositionHandler;
import com.cictec.middleware.gps.service.BusLineService;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.LineSegment;

/**
 * 服务器判定进出站信息
 * @author ql
 * @date 2017年8月31日
 */
public class BusPositionEnterOutJudgeHandler implements BusPositionHandler {


	private static Logger logger = LoggerFactory.getLogger(BusPositionEnterOutJudgeHandler.class);
	
	@Autowired
	private BusLineService busLineService;
	
	
	@Override
	public void onHandler(BusInstance busInstance) throws BusPositionHandlerException {
		
		// 判定是否服务器判定进出站信息
		boolean isServerJudjeEnterOut = PropertiesUtils.getBoolean("system.parameter.enterout.serverJudge", false);
		if(!isServerJudjeEnterOut){
			return;
		}
		
		List<BusLineStation> inStations = busLineService.getLineStationByPosition(busInstance.getLineUuid(), null, busInstance.getLatitude(), busInstance.getLongitude());
		
		TimingPoint prePoint = busInstance.getTimingPoint(-1);
		
		boolean isEnterOut = false;
		BusLineStation currentStation = null;
		
		if(prePoint == null){
			logger.debug("\t第一个点不判断");
		}else if (inStations.size() == 0) {
			// 【出站判定】
//			double moveAngle = getMoveAngle(busInstance, currentTime, latitude, longitude);
			if(busInstance.isInStation()){
				BusLineStation preLineStation = busLineService.getLineStationByStationSeq(busInstance.getLineUuid(), busInstance.getLineType(), busInstance.getStationSeq());
				currentStation = preLineStation;
				isEnterOut = true;
			}
			
			if(isEnterOut){
				builderEnterOutPosition(busInstance, currentStation, 2);
				logger.debug("\t【出站】");
			}else{
				logger.debug("\t【进站】【在站内】");
			}
		} else {
			
			// 【进站判定】
			double moveAngle = getMoveAngle(busInstance);
			String preLsUuid = busInstance.getStationUuidOrg();
			String enterout = busInstance.getStationEnterOut();
			
			if(PMSUtils.isEmpty(preLsUuid)){
				// 【进站】【无方向】【之前没有进出站信息】
				// 判定方向、方向角
				for (BusLineStation ls : inStations) {
					if(isSameEnterAngle(moveAngle, ls)){
						currentStation = ls;
						isEnterOut = true;
					}
				}
			}else{
				// 【进站】【有方向】【之前有进出站信息】
				if(busInstance.isInStation()){
					if(!hasStation(busInstance.getStationUuidOrg(), inStations)){
						// 判定方向、方向角
						for (BusLineStation ls : inStations) {
							if(isSameEnterAngle(moveAngle, ls)){
								currentStation = ls;
								isEnterOut = true;
							}
						}
					}
					
				}else{
					TimingPoint currentStationPoint = busInstance.getCurrentStation();
					if(!hasStation(currentStationPoint.getStationUuidOrg(), inStations)){
						// 判定方向、方向角
						for (BusLineStation ls : inStations) {
							if(isSameEnterAngle(moveAngle, ls)){
								currentStation = ls;
								isEnterOut = true;
							}
						}
					}
				}
				
			}
			
			if(isEnterOut){
				builderEnterOutPosition(busInstance, currentStation, 1);
				logger.debug("\t【进站】  ");
			}else{
				if(PMSUtils.isEmpty(enterout) || enterout.equals("0")){
					logger.debug("\t【02指令】【无方向】位置信息");
				}else{
					logger.debug("\t【02指令】【有方向】位置信息");
				}
			}
		}
	}

	/**
	 * 构建进出站信息
	 * @param busInstance
	 * @param orglineStation
	 * @param enterOutStatus
	 */
	private void builderEnterOutPosition(BusInstance busInstance, BusLineStation orglineStation, int enterOutStatus) {
		
		busInstance.setStationEnterOut(String.valueOf(enterOutStatus));

		// 站点信息
		BusLineStation lineStation;
		if (enterOutStatus == 1) {
			// 进站
			lineStation = orglineStation;
		} else {
			// 出站
			// 出站为下一个站点
			lineStation = busLineService.getLineStationByStationSeq(orglineStation.getLsLineUuid(), orglineStation.getLsLineType(), orglineStation.getLsSequence() + 1);
			if (lineStation == null) {
				lineStation = busLineService.getLineStationByStationSeq(orglineStation.getLsLineUuid(), orglineStation.getLsLineType(), 1);
			}
		}

		if (orglineStation != null) {
			busInstance.setStationLineSeqOrg(PMSUtils.isNull(orglineStation.getLsSequence()));
			busInstance.setStationLineTypeOrg(orglineStation.getLsLineType());
			busInstance.setStationNameOrg(orglineStation.getStaName());
			busInstance.setStationUuidOrg(orglineStation.getLsUuid());
		}

		if (lineStation != null) {
			
			busInstance.setAttributeStandBy(Constants.MSG_INFO_POSITION_STANDBY_FLAG_0);// 设置非代发区
			busInstance.setAttributeDeviate(Constants.VAL_IS_PX_0);	// 设置不偏线
			busInstance.setAttributeDrift(Constants.VAL_IS_PX_0);// 设置坐标不漂移
			busInstance.setLineType(lineStation.getLsLineType());	// 设置线路上下行
			busInstance.setStationUuid(lineStation.getLsUuid());
			busInstance.setStationName(lineStation.getStaName());
			busInstance.setStationSeq(String.valueOf(lineStation.getLsSequence()));// 设置所在站点序号

			busInstance.setAttribute("dataTypeTME", "TME");
		}
	}
	
	/**
	 * 判定当前站点集合中是否包含该站点
	 * 
	 * @param ls
	 * @param lss
	 * @return
	 */
	private boolean hasStation(String lsUuid, List<BusLineStation> lss) {
		String _lsUuid = PMSUtils.isNull(lsUuid);
		
		for (BusLineStation s : lss) {
			if (_lsUuid.equals(s.getLsUuid())) {
				return true;
			}
		}
		return false;
	}
	
	
	/**
	 * 判定是否是同方向进站角度
	 * @param moveAngle
	 * @param lineStation
	 * @return
	 */
	private boolean isSameEnterAngle(double moveAngle, BusLineStation lineStation){
		
		if (!Double.isNaN(lineStation.getEnterAngle()) 
				&& !Double.isNaN(moveAngle) 
				&& sameDirection(moveAngle, lineStation.getEnterAngle())) {
			return true;
		}
		return false;
	}
	
	/**
	 * 根据两个角度判断是否一个方向。
	 * @param ag1
	 * @param ag2
	 * @return
	 */
	private boolean sameDirection(double ag1, double ag2) {
		double offset = Math.abs(ag1 - ag2);
		if (offset > Math.PI) {
			offset = 2 * Math.PI - offset;
		}
		return offset <= Math.PI / 2;
	}
	
	
	private double getMoveAngle(BusInstance busInstance){
		// 【不同站点】前一个点站点信息与当前点不一致
		TimingPoint prePoint = busInstance.getTimingPoint(-1);
		
		return moveAngle(prePoint, busInstance);
	}
	
	/**
	 * 根据两个坐标计算行驶方向角
	 * @param prePos
	 * @param curPos
	 * @return
	 */
	private double moveAngle(TimingPoint prePos, TimingPoint curPos) {
		
		if(prePos == null || (prePos.getTime().getTime() - prePos.getTime().getTime() )>1000*60 ){
			//如果前一个坐标为null 或者前一个坐标的采集时间与当前坐标的采集时间差大于1分钟，返回无效夹角。
			return Double.NaN;
		}
		UTMPoint preUtmP = CoordinateConversion.latLon2UTM(prePos.getLatitude(), prePos.getLongitude());
		Coordinate preC = new Coordinate(preUtmP.getX(), preUtmP.getY());
		
		UTMPoint curUtmP = CoordinateConversion.latLon2UTM(curPos.getLatitude(), curPos.getLongitude());
		Coordinate curC = new Coordinate(curUtmP.getX(), curUtmP.getY());
		
		LineSegment moveLine = new LineSegment(preC,curC);
		
		return moveLine.angle();
	}
	
}
